package com.googlecode.mailnet.simulation;

import com.googlecode.mailnet.netmodel.MessageFlow;
import com.googlecode.mailnet.math.RandomUtil;
import com.googlecode.mailnet.info.IMessageListener;

import java.util.List;
import java.util.ArrayList;

/**
 * @author Iskander Akishev
 */
class MessageFlowState {
	final SimulationState simulationState;
	final MessageFlow messageFlow;
	final List<Message> undeliveredMessages;
	final NodeState sourceState;


    MessageFlowState(SimulationState simulationState, MessageFlow messageFlow) {
		this.simulationState = simulationState;
		this.messageFlow = messageFlow;
		undeliveredMessages = new ArrayList<Message>();
		sourceState = simulationState.nodeStates.get(messageFlow.getRoute().getSource());
	}

	/**
	 * Generates messages according to underlying {@link MessageFlow} configuration.
	 * This method will produce all undelivered messages as well as new ones.
	 * The messages will appear at the source node.
	 */
	void generateMessages() {
		if (sourceState.isBroken()) {
			return;
		}

        int messagesAmount = (RandomUtil.nextInteger(messageFlow.getMessagesAmountDistribution()) - undeliveredMessages.size());

		// Old messages retransmission.
		sourceState.currentInternalMessages.addAll(undeliveredMessages);
		undeliveredMessages.clear();

		// New messages generation.
		for (int i = 0; i < messagesAmount; i++) {
            int size = RandomUtil.nextInteger(messageFlow.getMessageSizeDistribution());
            // limit the size of the message with queue capacity for corresponding priority
            size = Math.min(size, simulationState.networkConfiguration.getQueueingConfiguration().getQueueLimit(messageFlow.getMessagesPriority()));

            Message newMessage = new Message(size, this, messageFlow.getMessagesPriority());
            for (IMessageListener messageListener : simulationState.messageListeners) {
                messageListener.onMessageCreated(newMessage);
            }
			sourceState.currentInternalMessages.add(newMessage);
		}
	}
}
